home *** CD-ROM | disk | FTP | other *** search
/ Sprite 1984 - 1993 / Sprite 1984 - 1993.iso / src / machserver / 1.098 / net / netCode.c < prev    next >
C/C++ Source or Header  |  1991-03-16  |  28KB  |  1,043 lines

  1. /* 
  2.  * netCode.c --
  3.  *
  4.  *    Various routines for initialzation, input and output.
  5.  *
  6.  *
  7.  * Copyright 1987 Regents of the University of California
  8.  * Permission to use, copy, modify, and distribute this
  9.  * software and its documentation for any purpose and without
  10.  * fee is hereby granted, provided that the above copyright
  11.  * notice appear in all copies.  The University of California
  12.  * makes no representations about the suitability of this
  13.  * software for any purpose.  It is provided "as is" without
  14.  * express or implied warranty.
  15.  */
  16.  
  17. #ifndef lint
  18. static char rcsid[] = "$Header: /sprite/src/kernel/net/RCS/netCode.c,v 9.7 91/03/15 15:47:07 jhh Exp Locker: mgbaker $ SPRITE (Berkeley)";
  19. #endif
  20.  
  21. #include <sprite.h>
  22. #include <list.h>
  23. #include <net.h>
  24. #include <netInt.h>
  25. #include <devNet.h>
  26. #include <sync.h>
  27. #include <dbg.h>
  28. #include <machMon.h>
  29. #include <netInet.h>
  30.  
  31. /*
  32.  * Network configuration table defined by machine dependent code.
  33.  */
  34. extern Net_Interface    netConfigInterfaces[];
  35. extern int        netNumConfigInterfaces;
  36. Net_Interface        *netInterfaces[NET_MAX_INTERFACES];
  37. int            netNumInterfaces;
  38.  
  39. Net_Address         netZeroAddress;
  40. int            net_NetworkHeaderSize[NET_NUM_NETWORK_TYPES];
  41.  
  42. #define    INC_BYTES_SENT(gatherPtr, gatherLength) { \
  43.     register    Net_ScatterGather    *gathPtr; \
  44.     int                    i; \
  45.     net_EtherStats.bytesSent += sizeof(Net_EtherHdr); \
  46.     for (i = gatherLength, gathPtr = gatherPtr; i > 0; i--, gathPtr++) { \
  47.         net_EtherStats.bytesSent += gathPtr->length; \
  48.     } \
  49.     }
  50. /*
  51.  * Macro to swap the fragOffset field.
  52.  */
  53. #define SWAP_FRAG_OFFSET_HOST_TO_NET(ptr) { \
  54.     unsigned short    *shortPtr; \
  55.     shortPtr = ((unsigned short *)&ptr->ident) + 1; \
  56.     *shortPtr = Net_HostToNetShort(*shortPtr); \
  57.  
  58. #define SWAP_FRAG_OFFSET_NET_TO_HOST(ptr) { \
  59.     unsigned short    *shortPtr; \
  60.     shortPtr = ((unsigned short *)&ptr->ident) + 1; \
  61.     *shortPtr = Net_NetToHostShort(*shortPtr); \
  62.  
  63. int netDebug = FALSE;
  64. Boolean    ultra = FALSE;
  65.  
  66. static void NetAddStats _ARGS_((Net_Stats *aPtr, Net_Stats *bPtr, 
  67.             Net_Stats *sumPtr));
  68. static void EnterDebugger _ARGS_((Net_Interface *interPtr, Address packetPtr,
  69.                 int packetLength));
  70.  
  71. /*
  72.  *----------------------------------------------------------------------
  73.  *
  74.  * Net_Init --
  75.  *
  76.  *    Initialize the network module data structures.
  77.  *
  78.  * Results:
  79.  *    None.
  80.  *
  81.  * Side effects:
  82.  *    None.
  83.  *
  84.  *----------------------------------------------------------------------
  85.  */
  86.  
  87. void
  88. Net_Init()
  89. {
  90.     register int i;
  91.     char buffer[100];
  92.     ReturnStatus status;
  93.     int        counter[NET_NUM_NETWORK_TYPES];
  94.     Net_Interface    *interPtr;
  95.  
  96.     NetEtherInit();
  97.  
  98.     for (i = 0; i < NET_NUM_NETWORK_TYPES; i++) {
  99.     counter[i] = 0;
  100.     }
  101.  
  102.     /*
  103.      * Determine the number and kind of network interfaces by calling
  104.      * each network interface initialization procedure.
  105.      */
  106.     bzero((char *) &netZeroAddress, sizeof(Net_Address));
  107.     netNumInterfaces = 0;
  108.     for (i = 0 ; i<netNumConfigInterfaces ; i++) {
  109.     netConfigInterfaces[i].flags = 0;
  110.     status = (netConfigInterfaces[i].init)(&(netConfigInterfaces[i]));
  111.     if (status == SUCCESS) {
  112.         netInterfaces[netNumInterfaces] = &netConfigInterfaces[i];
  113.         interPtr = netInterfaces[netNumInterfaces];
  114.         netNumInterfaces++;
  115.         interPtr->packetProc = NILPROC;
  116.         interPtr->devNetData = (ClientData) NIL;
  117.         interPtr->number = counter[interPtr->netType];
  118.         counter[interPtr->netType]++;
  119.         sprintf(buffer, "NetOutputMutex:%d", i);
  120.         Sync_SemInitDynamic(&interPtr->syncOutputMutex, 
  121.         buffer);
  122.         sprintf(buffer, "NetMutex:%d", i);
  123.         Sync_SemInitDynamic(&interPtr->mutex, buffer);
  124.     } 
  125.     }
  126.     net_NetworkHeaderSize[NET_NETWORK_ETHER] = sizeof(Net_EtherHdr);
  127.     net_NetworkHeaderSize[NET_NETWORK_ULTRA] = sizeof(Net_UltraHeader);
  128.     Net_ArpInit();
  129.     return;
  130. }
  131.  
  132. /*
  133.  *----------------------------------------------------------------------
  134.  *
  135.  * Net_Bin --
  136.  *
  137.  *    Bin various memory sizes allocated by the net module.
  138.  *
  139.  * Results:
  140.  *    None.
  141.  *
  142.  * Side effects:
  143.  *    Calls Mem_Bin to optimize memory allocation.
  144.  *
  145.  *----------------------------------------------------------------------
  146.  */
  147.  
  148. void
  149. Net_Bin()
  150. {
  151.     register int inter;
  152.     for (inter = 0 ; inter < netNumInterfaces ; inter++) {
  153.     Mem_Bin(netInterfaces[inter]->maxBytes);
  154.     }
  155.     return;
  156. }
  157.  
  158. /*
  159.  *----------------------------------------------------------------------
  160.  *
  161.  * Net_GatherCopy --
  162.  *
  163.  *    Copy all of the data pointed to by the scatter/gather array into
  164.  *    the destination.
  165.  *
  166.  * Results:
  167.  *    None.
  168.  *
  169.  * Side effects:
  170.  *    None.
  171.  *
  172.  *----------------------------------------------------------------------
  173.  */
  174.  
  175. void
  176. Net_GatherCopy(scatterGatherPtr, scatterGatherLength, destAddr)
  177.     register    Net_ScatterGather *scatterGatherPtr;
  178.     int                    scatterGatherLength;
  179.     register    Address          destAddr;
  180. {
  181.     int i;
  182.     int soFar = 0;
  183.  
  184.     for (i = 0; i < scatterGatherLength; i++, scatterGatherPtr++) {
  185.     if (scatterGatherPtr->length == 0) {
  186.         continue;
  187.     }
  188.  
  189.     bcopy((Address) scatterGatherPtr->bufAddr, 
  190.          (Address) &(destAddr[soFar]), 
  191.          scatterGatherPtr->length);
  192.     soFar += scatterGatherPtr->length;
  193.     }
  194.     return;
  195. }
  196.  
  197.  
  198.  
  199. /*
  200.  *----------------------------------------------------------------------
  201.  *
  202.  * Net_Reset --
  203.  *
  204.  *    Reset the network interface.
  205.  *
  206.  * Results:
  207.  *    None.
  208.  *
  209.  * Side effects:
  210.  *    Reinitializes the network controller..
  211.  *
  212.  *----------------------------------------------------------------------
  213.  */
  214. void
  215. Net_Reset(interPtr)
  216.     Net_Interface    *interPtr;
  217. {
  218.     interPtr->reset(interPtr);
  219. }
  220.  
  221.  
  222. /*
  223.  *----------------------------------------------------------------------
  224.  *
  225.  * Net_Output --
  226.  *
  227.  *    Send a packet to a host identified by a Sprite Host ID.
  228.  *
  229.  * Results:
  230.  *    SUCCESS     - the operation was successful.
  231.  *    FAILURE        - there was no route to the host or 
  232.  *              the Sprite host ID was bad or 
  233.  *              an unknown route type was found.
  234.  *
  235.  * Side effects:
  236.  *    Sends the packet.
  237.  *    If no route has been established to the SpriteID then the
  238.  *    Address Resolution Protocol (ARP) is invoked to find the
  239.  *    physical address corresponding to the SpriteID.
  240.  *
  241.  *----------------------------------------------------------------------
  242.  */
  243.  
  244. ReturnStatus
  245. Net_Output(spriteID, gatherPtr, gatherLength, mutexPtr, routePtr)
  246.     int spriteID;            /* Host to which to send the packet */
  247.     Net_ScatterGather *gatherPtr;    /* Specifies buffers containing the
  248.                      * pieces of the packet The first
  249.                      * element of gatherPtr is assumed to 
  250.                      * be a buffer large enought to 
  251.                      * format any protocol headers
  252.                      * we need. */
  253.     int gatherLength;            /* Number of elements in gatherPtr[] */
  254.     Sync_Semaphore *mutexPtr;        /* Mutex that is released during the
  255.                      * ARP transaction (if needed).  This
  256.                      * doesn't mess up the caller because
  257.                      * its packet isn't output until
  258.                      * the ARP completes anyway */
  259.     Net_Route    *routePtr;        /* If non-NIL then used as the route
  260.                      * to send the packet. */
  261. {
  262.     Net_Interface    *interPtr;
  263.     Boolean        ourRoute = FALSE;
  264.     ReturnStatus    status;
  265.  
  266.     if (spriteID < 0 || spriteID >= NET_NUM_SPRITE_HOSTS) {
  267.     return(NET_UNREACHABLE_NET);
  268.     }
  269.  
  270.     /*
  271.      * Check for a route to the indicated host.  Use ARP to find it if needed.
  272.      */
  273.     if (routePtr == (Net_Route *) NIL) {
  274.     ourRoute = TRUE;
  275.     routePtr = Net_IDToRoute(spriteID, 0, TRUE, mutexPtr, 0);
  276.     if (routePtr == (Net_Route *)NIL) {
  277.         return(NET_UNREACHABLE_NET);
  278.     }
  279.     }
  280.     interPtr = routePtr->interPtr;
  281.     switch(routePtr->protocol) {
  282.     case NET_PROTO_RAW : {
  283.         /*
  284.          * The first gather buffer contains the protocol header for
  285.          * which we have none for the ethernet.
  286.          */
  287.         gatherPtr->length = 0;     
  288.         gatherPtr->done = FALSE;
  289.         gatherPtr->mutexPtr = mutexPtr;
  290.         status = (interPtr->output) (interPtr, 
  291.             routePtr->headerPtr[NET_PROTO_RAW], 
  292.             gatherPtr, gatherLength, TRUE, &status);
  293.         if (status == SUCCESS) {
  294.             while (!gatherPtr->done && 
  295.             mutexPtr != (Sync_Semaphore *)NIL) {
  296.             (void) Sync_SlowMasterWait((unsigned int)mutexPtr, 
  297.                 mutexPtr, 0);
  298.             }
  299.         }
  300.         break;
  301.         }
  302.     case NET_PROTO_INET: {
  303.         /*
  304.          * For the INET routes we must fill in the ipHeader in the 
  305.          * first buffer of the gather array. 
  306.          */
  307.         register Net_IPHeader        *ipHeaderPtr;
  308.         register unsigned int length;
  309.         register Net_ScatterGather    *gathPtr;
  310.         register int     i; 
  311.  
  312.         /*
  313.          * Compute the length of the gather vector. 
  314.          */
  315.         length = sizeof(Net_IPHeader);
  316.         gathPtr = gatherPtr + 1;
  317.         for (i = 1; i < gatherLength;  i++, gathPtr++){
  318.             length += gathPtr->length; 
  319.         }
  320.  
  321.  
  322.         /*
  323.          * Fill the  ipHeader into the first element of the 
  324.          * scatter/gather from the template stored in the route
  325.          * data.
  326.          */
  327.         gatherPtr->length = sizeof(Net_IPHeader);
  328.         ipHeaderPtr = (Net_IPHeader *) gatherPtr->bufAddr;
  329.         gatherPtr->done = FALSE;
  330.         gatherPtr->mutexPtr = mutexPtr;
  331.  
  332.         *ipHeaderPtr = *(Net_IPHeader *) 
  333.                     routePtr->headerPtr[NET_PROTO_INET];
  334.         /*
  335.          * Update length and checksum. The template 
  336.          * ipHeaderPtr->checksum should contain the 16 bit sum of 
  337.          * the IP header with totalLen set to zero. We add the
  338.          * new total length and convert into one-complement.
  339.          * See Net_InetChecksum().
  340.          */
  341.         length = Net_HostToNetShort(length);
  342.         ipHeaderPtr->totalLen = length;
  343.  
  344.         length = ipHeaderPtr->checksum + length;
  345.         ipHeaderPtr->checksum = ~(length + (length >> 16));
  346.  
  347.         status = (interPtr->output)(interPtr, 
  348.             routePtr->headerPtr[NET_PROTO_RAW], gatherPtr, 
  349.             gatherLength, FALSE, &status);
  350.         if (status == SUCCESS) {
  351.             while (!gatherPtr->done && 
  352.             mutexPtr != (Sync_Semaphore *)NIL) {
  353.             (void) Sync_SlowMasterWait((unsigned int)mutexPtr, 
  354.                     mutexPtr, 0);
  355.             }
  356.         }
  357.         break;
  358.         }
  359.     default:
  360.         printf("Warning: Net_Output: unsupported route protocol: %x\n", 
  361.             routePtr->protocol);
  362.         panic(NIL);
  363.         status = FAILURE;
  364.     }
  365.     if (ourRoute) {
  366.     Net_ReleaseRoute(routePtr);
  367.     }
  368.     return status;
  369. }
  370.  
  371.  
  372.  
  373. /*
  374.  *----------------------------------------------------------------------
  375.  *
  376.  * Net_RawOutput --
  377.  *
  378.  *    Send a packet directly onto the network.
  379.  *
  380.  * Results:
  381.  *    SUCCESS if the packet made it as far as the network interface,
  382.  *    a failure code otherwise.  SUCCESS does not imply that the
  383.  *    packet was actually sent because the interface could have
  384.  *    rejected it.
  385.  *
  386.  * Side effects:
  387.  *    None.
  388.  *
  389.  *----------------------------------------------------------------------
  390.  */
  391.  
  392. ReturnStatus
  393. Net_RawOutput(interPtr, headerPtr, gatherPtr, gatherLength)
  394.     Net_Interface    *interPtr;    /* The network interface. */
  395.     Address        headerPtr;    /* Packet header. */
  396.     Net_ScatterGather    *gatherPtr;    /* Specifies buffers containing the
  397.                      * pieces of the packet */
  398.     int         gatherLength;    /* Number of elements in gatherPtr[] */
  399. {
  400.     return (interPtr->output)(interPtr, headerPtr, gatherPtr, gatherLength, 
  401.         FALSE, (ReturnStatus *) NIL);
  402. }
  403.  
  404.  
  405. /*
  406.  *----------------------------------------------------------------------
  407.  *
  408.  * Net_RecvPoll --
  409.  *
  410.  *    See if a packet has come in.  If one has come in then it is assumed
  411.  *    that the packet processing routine will get called.  Thus this routine
  412.  *    does not return any value; it is up to the packet processing routine
  413.  *    to set some global state.  This is intended to be used by the
  414.  *    debugger.
  415.  *
  416.  * Results:
  417.  *    None.
  418.  *
  419.  * Side effects:
  420.  *    None.
  421.  *
  422.  *----------------------------------------------------------------------
  423.  */
  424.  
  425. void
  426. Net_RecvPoll(interPtr)
  427.     Net_Interface    *interPtr;    /* Network interface. */
  428. {
  429.     if (netDebug) {
  430.     printf("Net_RecvPoll\n");
  431.     }
  432.     (interPtr->intr)(interPtr, TRUE);
  433. }
  434.  
  435.  
  436. /*
  437.  *----------------------------------------------------------------------
  438.  *
  439.  * Net_RawOutputSync --
  440.  *
  441.  *     Send a packet on the network. Does not return until the packet
  442.  *    is actually sent.
  443.  *
  444.  * Results:
  445.  *    SUCCESS if the packet was sent correctly, otherwise a standard
  446.  *    Sprite return status.
  447.  *
  448.  * Side effects:
  449.  *    None.
  450.  *
  451.  *----------------------------------------------------------------------
  452.  */
  453. ReturnStatus
  454. Net_RawOutputSync(interPtr, headerPtr, gatherPtr, gatherLength)
  455.     Net_Interface    *interPtr;    /* Network interface. */
  456.     Address        headerPtr;    /* Packet header. */
  457.     Net_ScatterGather     *gatherPtr;    /* Specifies buffers containing the
  458.                      * pieces of the packet */
  459.     int         gatherLength;    /* Number of elements in gatherPtr[] */
  460. {
  461.     ReturnStatus    status;
  462.  
  463.     gatherPtr->mutexPtr = &(interPtr->syncOutputMutex);
  464.     gatherPtr->done = FALSE;
  465.  
  466.     MASTER_LOCK(&(interPtr->syncOutputMutex));
  467.  
  468.     status = (interPtr->output)(interPtr, headerPtr, gatherPtr, gatherLength, 
  469.     FALSE, &status);
  470.     if (status == SUCCESS) {
  471.     while (!gatherPtr->done) {
  472.         (void) Sync_SlowMasterWait(
  473.             (unsigned int)&(interPtr->syncOutputMutex), 
  474.             &(interPtr->syncOutputMutex), FALSE);
  475.     }
  476.     }
  477.     MASTER_UNLOCK(&(interPtr->syncOutputMutex));
  478.     return status;
  479. }
  480.  
  481. /*
  482.  *----------------------------------------------------------------------
  483.  *
  484.  * NetOutputWakeup --
  485.  *
  486.  *    Called to notify a waiter that a packet has been sent.  This is
  487.  *    hacked up now, as the argument is really a mutexPtr which
  488.  *    has been used as a raw event to wait on.  We have to use
  489.  *    the raw SlowBroadcast procedure because of this.
  490.  *
  491.  * Results:
  492.  *    None.
  493.  *
  494.  * Side effects:
  495.  *    None.
  496.  *
  497.  *----------------------------------------------------------------------
  498.  */
  499.  
  500. void
  501. NetOutputWakeup(mutexPtr)
  502.     Sync_Semaphore    *mutexPtr;    /* Mutex from scatter/gather struct */
  503. {
  504.     int waiting;
  505.  
  506.     /*
  507.      * FIX THIS.
  508.      */
  509.     if (dbg_UsingNetwork) {
  510.     return;
  511.     }
  512.  
  513. #if (MACH_MAX_NUM_PROCESSORS == 1) /* uniprocessor implementation */
  514.     (void) Sync_SlowBroadcast((unsigned int)mutexPtr, &waiting);
  515. #else     /* Mutiprocessor implementation */
  516.    /*
  517.     * Because the packet sent interrupt may come in before Net_Output
  518.     * has a chance to MasterWait and after Net_Output has checked the
  519.     * gatherPtr->done flag, the code should syncronize with the caller
  520.     * by obtaining the master lock.
  521.     */
  522.     MASTER_LOCK(mutexPtr);
  523.     (void) Sync_SlowBroadcast((unsigned int) mutexPtr, &waiting);    
  524.     MASTER_UNLOCK(mutexPtr);
  525. #endif
  526.     return;
  527. }
  528.  
  529.  
  530. /*
  531.  *----------------------------------------------------------------------
  532.  *
  533.  * Net_Intr --
  534.  *
  535.  *    The interrupt routine which is called when the ethernet chip 
  536.  *    interrupts the processor.  All this routine does is to branch
  537.  *    to the interrupt handler for the type of ethernet device
  538.  *    present on the machine.  The device driver, in turn, eventually
  539.  *    calls Net_Input to pass the packet to the correct protocol handler.
  540.  *
  541.  * Results:
  542.  *    None.
  543.  *
  544.  * Side effects:
  545.  *    None.
  546.  *
  547.  *----------------------------------------------------------------------
  548.  */
  549.  
  550. int
  551. Net_Intr(interPtr)
  552.     Net_Interface    *interPtr;    /* Network interface. */
  553. {
  554.     if (netDebug) {
  555.     printf("Received an interrupt on interface %s\n", interPtr->name);
  556.     }
  557.     (interPtr->intr)(interPtr, FALSE);
  558.     return 1;
  559. }
  560.  
  561. /*
  562.  *----------------------------------------------------------------------
  563.  *
  564.  * Net_Input --
  565.  *
  566.  *    A stub called by device drivers to pass off packets to protocols.
  567.  *    This could be a macro.
  568.  *
  569.  *    The packet handler called must copy the packet to private buffers.
  570.  *
  571.  *    TODO:
  572.  *        This routine, and the ones it calls, should not assume
  573.  *        that there is a packet header at the start of the
  574.  *        packet.  The header should be passed separately.
  575.  *
  576.  * Results:
  577.  *    None.
  578.  *
  579.  * Side effects:
  580.  *    None.  
  581.  *
  582.  *----------------------------------------------------------------------
  583.  */
  584.  
  585. void
  586. Net_Input(interPtr, packetPtr, packetLength)
  587.     Net_Interface *interPtr;    /* Network interface. */
  588.     Address packetPtr;        /* The packet. */
  589.     int packetLength;        /* The length of the packet. */
  590. {
  591.     int        headerSize;
  592.     int        packetType = NET_PACKET_UNKNOWN;
  593.     Boolean    ultra = FALSE;
  594.  
  595. #if 0
  596.     printf("in Net_Input\n");
  597.     printf("Net_Input(0x%x, 0x%x, 0x%x)\n", interPtr, packetPtr, packetLength);
  598.     printf("netType = %08x\n", interPtr->netType);
  599. #endif
  600.  
  601.     if (netDebug) {
  602.     printf("Net_Input(0x%x, 0x%x, 0x%x) netType = %08x\n",
  603.         interPtr, packetPtr, packetLength, interPtr->netType);
  604.     }
  605.     switch(interPtr->netType) {
  606.     case NET_NETWORK_ETHER : {
  607.         Net_EtherHdr *etherHdrPtr;
  608.         int        type;
  609.         etherHdrPtr = (Net_EtherHdr *)packetPtr;
  610.         type = Net_NetToHostShort((unsigned short)
  611.             NET_ETHER_HDR_TYPE(*etherHdrPtr));
  612.         switch(type) {
  613.         case NET_ETHER_SPRITE:
  614.             packetType = NET_PACKET_SPRITE;
  615.             break;
  616.         case NET_ETHER_ARP:
  617.             packetType = NET_PACKET_ARP;
  618.             break;
  619.         case NET_ETHER_REVARP:
  620.             packetType = NET_PACKET_RARP;
  621.             break;
  622.         case NET_ETHER_SPRITE_DEBUG:
  623.             packetType = NET_PACKET_DEBUG;
  624.             break;
  625.         case NET_ETHER_IP:
  626.             packetType = NET_PACKET_IP;
  627.             break;
  628.         default:
  629.             packetType = NET_PACKET_UNKNOWN;
  630.             break;
  631.         }
  632.         ultra = FALSE;
  633.         break;
  634.     }
  635.     case NET_NETWORK_ULTRA: {
  636.         Net_UltraHeader    *ultraHdrPtr;
  637.         ultraHdrPtr = (Net_UltraHeader *) packetPtr;
  638.         ultra = TRUE;
  639.         if ((ultraHdrPtr->localAddress.tsapSize == 2) &&
  640.         (ultraHdrPtr->localAddress.tsap[0] == (unsigned char) 0xff) &&
  641.         (ultraHdrPtr->localAddress.tsap[1] == (unsigned char) 0xff)) {
  642.         packetType = NET_PACKET_SPRITE;
  643.         } else {
  644.         packetType = NET_PACKET_UNKNOWN;
  645.         }
  646.         break;
  647.     }
  648.     default : 
  649.         printf("Net_Input: invalid net type %d\n", interPtr->netType);
  650.     }
  651.     headerSize = net_NetworkHeaderSize[interPtr->netType];
  652.     if (dbg_UsingNetwork) {
  653.     /*
  654.      * If the kernel debugger is running it gets all the packets. We
  655.      * process ARP requests to allow hosts to talk to the debugger.
  656.      */
  657.     if (packetType == NET_PACKET_ARP) {
  658.             NetArpInput(interPtr, packetPtr, packetLength);
  659.     } else { 
  660.         Dbg_InputPacket(interPtr, packetPtr, packetLength);
  661.     }
  662.     return;
  663.     }
  664.     switch(packetType) {
  665.         case NET_PACKET_SPRITE:
  666.         if (netDebug) {
  667.         printf("Received a Sprite packet, calling Rpc_Dispatch\n");
  668.         }
  669.             Rpc_Dispatch(interPtr, NET_PROTO_RAW, packetPtr, 
  670.              (Address) (((char *) packetPtr) + headerSize), 
  671.              packetLength - headerSize);
  672.             break;
  673.  
  674.         case NET_PACKET_ARP:
  675.     case NET_PACKET_RARP:
  676.         /*
  677.          * The kernel gets first shot at ARP packets and then they are
  678.          * forward to tbe /dev/net device.
  679.          */
  680.         if (netDebug) {
  681.         if (packetType == NET_PACKET_ARP) {
  682.             printf("Received an ARP packet.\n");
  683.         } else {
  684.             printf("Received a RARP packet.\n");
  685.         }
  686.         }
  687.             NetArpInput(interPtr, packetPtr, packetLength);
  688.         if (interPtr->packetProc != NILPROC) {
  689.         (interPtr->packetProc)(interPtr, packetLength, packetPtr);
  690.         }
  691.         break;
  692.  
  693.         case NET_PACKET_DEBUG:
  694.         if (netDebug) {
  695.         printf("Received a debug packet.\n");
  696.         }
  697.             EnterDebugger(interPtr, packetPtr, packetLength);
  698.             break;
  699.  
  700.     case NET_PACKET_IP: {
  701.         register Net_IPHeader *ipHeaderPtr = 
  702.             (Net_IPHeader *) (packetPtr + headerSize);
  703.         /*
  704.          * The kernel steals IP packets with the Sprite RPC protocol number.
  705.          */
  706.         if (netDebug) {
  707.         printf("Received an IP packet.\n");
  708.         }
  709.         if ( (packetLength > sizeof(Net_IPHeader)+headerSize) && 
  710.              (ipHeaderPtr->protocol == NET_IP_PROTOCOL_SPRITE)) {
  711.         int    headerLenInBytes;
  712.         int    totalLenInBytes;
  713.         headerLenInBytes = ipHeaderPtr->headerLen * 4;
  714.         totalLenInBytes = Net_NetToHostShort(ipHeaderPtr->totalLen);
  715.         /*
  716.          * Validate the packet. We toss out the following cases:
  717.          * 1) Runt packets.
  718.          * 2) Bad checksums.
  719.          * 3) Fragments.
  720.          * Since we sent the packets with dont fragment set we 
  721.          * shouldn't get any fragments.
  722.          */
  723.         if ((headerLenInBytes >= sizeof(Net_IPHeader)) &&
  724.              (totalLenInBytes > headerLenInBytes) &&
  725.              (totalLenInBytes <= (packetLength-headerSize)) &&
  726.              (Net_InetChecksum(headerLenInBytes, (Address)ipHeaderPtr)
  727.                                 == 0)) {
  728.  
  729.             SWAP_FRAG_OFFSET_NET_TO_HOST(ipHeaderPtr);
  730.             if((!(ipHeaderPtr->flags & NET_IP_MORE_FRAGS)) &&
  731.               (ipHeaderPtr->fragOffset == 0)) {
  732.             if (netDebug) {
  733.                 printf(
  734.             "Received a Sprite IP packet, calling Rpc_Dispatch\n");
  735.             }
  736.             Rpc_Dispatch(interPtr, NET_PROTO_INET, packetPtr, 
  737.                    (Address)(((char *) ipHeaderPtr) + headerLenInBytes),
  738.                      totalLenInBytes-headerLenInBytes);
  739.              }
  740.         }
  741.  
  742.         } else {
  743.  
  744.         if (interPtr->packetProc != NILPROC) {
  745.             (interPtr->packetProc)(interPtr, packetLength, packetPtr);
  746.         }
  747.         }
  748.         break;
  749.     }
  750.     default:
  751.         if (netDebug) {
  752.         printf("Received a packet with unknown type 0x%x.\n",
  753.             packetType);
  754.         }
  755.         if (interPtr->packetProc != NILPROC) {
  756.         (interPtr->packetProc)(interPtr, packetLength, packetPtr);
  757.         }
  758.         break;
  759.     }
  760.     return;
  761. }
  762.  
  763.  
  764. /*
  765.  *----------------------------------------------------------------------
  766.  *
  767.  * EnterDebugger --
  768.  *
  769.  *    Processes the special NET_ETHER_SPRITE_DEBUG packet type.
  770.  *    Prints the data in the packet (which is the hostname of the sender)
  771.  *    and then enters the debugger. The format of data in the packet is:
  772.  *     1) size of sender's name in bytes (4 bytes),
  773.  *     2) the sender's name (max 100 bytes).
  774.  *
  775.  * Results:
  776.  *    None.
  777.  *
  778.  * Side effects:
  779.  *    Enters the debugger.
  780.  *
  781.  *----------------------------------------------------------------------
  782.  */
  783.  
  784. /* ARGSUSED */
  785. static void
  786. EnterDebugger(interPtr, packetPtr, packetLength)
  787.     Net_Interface    *interPtr;
  788.     Address packetPtr;
  789.     int packetLength;
  790. {
  791.     char *name;
  792.     unsigned int  len;
  793.  
  794.     packetPtr += net_NetworkHeaderSize[interPtr->netType];
  795.     /*
  796.      * Copy the length out of the packet into a correctly aligned integer.
  797.      * Correct its byte order.
  798.      */
  799.     bcopy( packetPtr, (Address) &len, sizeof(len));
  800.  
  801.     len = Net_NetToHostInt(len);
  802.  
  803.     /*
  804.      * Validate the data length and make sure the name is null-terminated.
  805.      */
  806.     if (len < 100) {
  807.     name = (char *) (packetPtr + sizeof(len));
  808.     name[len] = '\0';
  809.     printf("\n*** Got a debugger packet from %s ***\n", name);
  810.     } else {
  811.     printf("\n*** Got a debugger packet ***\n");
  812.     }
  813.  
  814.     DBG_CALL;
  815.     return;
  816. }
  817.  
  818. /*
  819.  *----------------------------------------------------------------------
  820.  *
  821.  * Net_GetInterface --
  822.  *
  823.  *    Returns a pointer to the interface structure with the
  824.  *    given number and type.
  825.  *
  826.  * Results:
  827.  *    A pointer to a Net_Interface if one with the given number
  828.  *    exists, NIL otherwise.
  829.  *
  830.  * Side effects:
  831.  *    None.
  832.  *
  833.  *----------------------------------------------------------------------
  834.  */
  835.  
  836. Net_Interface *
  837. Net_GetInterface(netType, number)
  838.     Net_NetworkType    netType;    /* Type of interface. */
  839.     int            number;        /* Number of interface. */
  840. {
  841.     Net_Interface    *interPtr;
  842.     register int    i;
  843.  
  844.     interPtr = (Net_Interface *) NIL;
  845.     for (i = 0; i < netNumInterfaces; i++) {
  846.     if (netInterfaces[i]->netType == netType &&
  847.         netInterfaces[i]->number == number) {
  848.         interPtr = netInterfaces[i];
  849.         break;
  850.     }
  851.     }
  852.     return interPtr;
  853. }
  854.  
  855. /*
  856.  *----------------------------------------------------------------------
  857.  *
  858.  * Net_NextInterface --
  859.  *
  860.  *     This routine can be used to iterate through all network
  861.  *    interfaces, regardless of type.  The parameter 'index'
  862.  *    is used to keep track of where we are in the interaction.
  863.  *    A pointer will be returned to first interface whose index
  864.  *    is equal to or greater than 'index' and that is running.
  865.  *    The 'index' parameter will be set to the index of the
  866.  *    interface upon return.  
  867.  *
  868.  * Results:
  869.  *    A pointer to the first interface whose number if greater than
  870.  *    or equal to the contents of indexPtr and is running. NIL
  871.  *    if no such interface exists.
  872.  *
  873.  * Side effects:
  874.  *    None.
  875.  *
  876.  *----------------------------------------------------------------------
  877.  */
  878.  
  879. Net_Interface *
  880. Net_NextInterface(running, indexPtr)
  881.     Boolean        running;    /* TRUE => returned interface    
  882.                      * must be in running state. */
  883.     int            *indexPtr;    /* Ptr to index to use. */
  884. {
  885.     register int    i;
  886.  
  887.     for (i = *indexPtr; i < netNumInterfaces; i++) {
  888.     if (netDebug) {
  889.         printf("i = %d, name = %s, running = %d\n", i, 
  890.         netInterfaces[i]->name, 
  891.         netInterfaces[i]->flags & NET_IFLAGS_RUNNING);
  892.     }
  893.     if (!running || netInterfaces[i]->flags & NET_IFLAGS_RUNNING) {
  894.         *indexPtr = i;
  895.         return netInterfaces[i];
  896.     }
  897.     }
  898.     return (Net_Interface *) NIL;
  899. }
  900.  
  901. /*
  902.  *----------------------------------------------------------------------
  903.  *
  904.  * Net_SetPacketHandler --
  905.  *
  906.  *    Routine to register a callback for each packet received
  907.  *    on a particular network interface.
  908.  *    Right now the Net_Input routine knows about the different
  909.  *     types of packets and knows which routines to call.  This
  910.  *    routine is used to set the callback for generic packets
  911.  *    so that the dev module sees them. 
  912.  *
  913.  *    The handler parameter should have the following definition:
  914.  *        void    handler(interPtr, packetPtr, size)
  915.  *            Net_Interface    *interPtr; 
  916.  *            Address        packetPtr; 
  917.  *            int        size;       
  918.  *
  919.  *    TODO:  It would probably be nice to classify packets (rpc, ip,
  920.  *        ether, etc) and register interest in the different
  921.  *        classifications. That would make Net_Input more
  922.  *        general.
  923.  *
  924.  * Results:
  925.  *    None.
  926.  *
  927.  * Side effects:
  928.  *    The function parameter will be called for all 'normal' network
  929.  *    packets.
  930.  *
  931.  *----------------------------------------------------------------------
  932.  */
  933.  
  934. void
  935. Net_SetPacketHandler(interPtr, handler)
  936.     Net_Interface    *interPtr;    /* The interface. */
  937.     void        (*handler)();    /* Packet handling routine. */
  938. {
  939.     interPtr->packetProc = handler;
  940. }
  941.  
  942. /*
  943.  *----------------------------------------------------------------------
  944.  *
  945.  * Net_RemovePacketHandler --
  946.  *
  947.  *    Routine to remove a packet handler callback procedure.
  948.  *
  949.  * Results:
  950.  *    None.
  951.  *
  952.  * Side effects:
  953.  *    None.
  954.  *
  955.  *----------------------------------------------------------------------
  956.  */
  957.  
  958. void
  959. Net_RemovePacketHandler(interPtr)
  960.     Net_Interface    *interPtr;    /* The interface. */
  961. {
  962.     interPtr->packetProc = NILPROC;
  963. }
  964.  
  965. /*
  966.  *----------------------------------------------------------------------
  967.  *
  968.  * Net_GetStats --
  969.  *
  970.  *    Returns the event statistics for the various network 
  971.  *    interfaces.  The sum of the stats for all interfaces of the
  972.  *    given type is returned.
  973.  *
  974.  * Results:
  975.  *    SUCCESS if the statistics are returned, an error code otherwise
  976.  *
  977.  * Side effects:
  978.  *    None.
  979.  *
  980.  *----------------------------------------------------------------------
  981.  */
  982.  
  983. ReturnStatus
  984. Net_GetStats(netType, statPtr)
  985.     Net_NetworkType    netType;     /* Type of interfaces to get stats
  986.                      * for. */
  987.     Net_Stats        *statPtr;    /* Statistics to fill in. */ 
  988. {
  989.     int            i;
  990.     ReturnStatus    status = SUCCESS;
  991.     Net_Stats        tmpStats;
  992.  
  993.     bzero((char *) statPtr, sizeof(Net_Stats));
  994.     for (i = 0; i < netNumInterfaces; i++) {
  995.     if ((netInterfaces[i]->flags & NET_IFLAGS_RUNNING) &&
  996.         (netInterfaces[i]->netType == netType)) {
  997.         status = (netInterfaces[i]->getStats)(netInterfaces[i], &tmpStats);
  998.         if (status != SUCCESS) {
  999.         break;
  1000.         }
  1001.         NetAddStats(&tmpStats, statPtr, statPtr);
  1002.     }
  1003.     }
  1004.     return status;
  1005. }
  1006.  
  1007.  
  1008. /*
  1009.  *----------------------------------------------------------------------
  1010.  *
  1011.  * NetAddStats --
  1012.  *
  1013.  *    Add two stats structures together. This routine assumes that
  1014.  *    the structures are composed of only integers.
  1015.  *
  1016.  * Results:
  1017.  *    None.
  1018.  *
  1019.  * Side effects:
  1020.  *    None.
  1021.  *
  1022.  *----------------------------------------------------------------------
  1023.  */
  1024.  
  1025. static void
  1026. NetAddStats(aPtr, bPtr, sumPtr)
  1027.     Net_Stats *aPtr;            /* First addend. */
  1028.     Net_Stats *bPtr;            /* Second addend. */
  1029.     Net_Stats *sumPtr;            /* The sum of the two. */
  1030. {
  1031.     Net_Stats        tmp;
  1032.     int            i;
  1033.  
  1034.     bzero((char *) &tmp, sizeof(tmp));
  1035.     for (i = 0; i < sizeof(Net_Stats) / sizeof(int); i++) {
  1036.     ((int *) &tmp)[i] = ((int *) aPtr)[i] + ((int *) bPtr)[i];
  1037.     }
  1038.     bcopy((char *) &tmp, (char *) sumPtr, sizeof(Net_Stats));
  1039. }
  1040.  
  1041.